/** @file desc.h
 *
 * @brief Descriptive (RDF) resource.
 *
 * The Descriptive Resource (DESC-R), together with the Data Resource (DATA-R),
 * is the building block of lsup_repo information. Its contents are fully
 * understood by the library.
 */

#ifndef _LSR_DESC_H
#define _LSR_DESC_H

#include "core.h"


/*
 * Typedefs.
 */

/** @brief DESC-R structure.
 *
 * A Descriptive Resource (DESC-R) is made up of several RDF named graphs.
 * Each graph has a function defined by the framework and can be managed by
 * the framework or by the user.
 *
 * the URI of each graph is derived from the ID of the resource. This is just
 * for readability. Actually, when stored, the resource generates triples that
 * explicitly link these graphs together. These URIs have an URN prefix so that
 * they are portable and, in a Linked Data server, can be easily replaced with
 * absolute URLs based on the server root.
 *
 * The `user_data` handle is a {NULL}-terminated array of user-defined graphs.
 * Each graph URI is considered relative to the resource URN and may or may not
 * be consistent across resources, depending on how repository managers
 * organize their knowledge.
 *
 * The `admin_data` graph contains exclusively triples managed by the
 * repository.  They may have special functionality attached and may be created
 * as a direct consequence of a user action (e.g. adding a member to a Set or
 * List).
 *
 * Relationships between these graphs are expressed by triples stored in the
 * default graph.
 */
typedef struct desc_t {
    LSUP_Graph **           user_data;      ///< User-defined data graphs.
    LSUP_Graph *            admin_data;     ///< Managed data (one graph).
    LSUP_Graph *            main_data;      ///< Relationships between graphs.
    uuid_t                  id;             ///< Resource identifier (RFC4122).
    LSR_ResFlags            flags;          ///< Flags.
} LSR_Desc;


/*
 * API functions.
 */

/** @brief Create an in-memory DESC-R from multiple graphs.
 *
 * The resource is volatile until it is stored in a persistent back end. It
 * must be stored in a context-capable back end (e.g. `LSUP_STORE_MDB`).
 *
 * The resource is assigned a UUID4. The resource URI, used in
 * relationships, is the ID prefixed with the `LSR_NS_DESC` namespace.
 *
 * @param[in] data NULL-terminated array of graph handles, each with a set of
 *  triples to populate the new resource. Triples and terms are copied and get
 *  freed when #LSR_desc_free() is called. All URIs, including the graph URI,
 *  if not absolute, are intended as relative to the resource URI.  Hence, to
 *  reference the resource itself, an IRIRef with an empty string as data may
 *  be used. The graph URI is maintained within the resource. As a convention,
 *  it is recommended to use a fragment URI with a short label, e.g.
 *  `#set37205`, `#~alice`, or `#ancillary`. Fragments beginning with two
 *  underscores are reserved for internal use and are not allowed in the input.
 *
 * @param[out] rsrc Resource handle pointer. The handle should be freed with
 *  #LSR_desc_free(). On a non-success return code, the handle may be garbage.
 *
 * @return LSUP_OK on success; < 0 on error.
 */
LSUP_rc
LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc);


/** @brief Shortcut to create a resource from a single graph.
 *
 * The graph is automatically assigned the `_main` label. See
 * #LSR_desc_new_multi for other documentation.
 *
 * @param[in] data Single graph to insert.
 *
 * @param[out] rsrc Resource handle pointer. The handle should be freed with
 *  #LSR_desc_free(). On a non-success return code, the handle may be garbage.
 *
 * @return LSUP_OK on success; < 0 on error.
 */
LSUP_rc
LSR_desc_new (const LSUP_Graph *data, LSR_Desc **rsrc);



/** @brief Create an in-memory DESC-R from a stored resource.
 *
 * Once created, the resource may be modified independently from its stored
 * counterpart. In order to make changes permanent, it must be stored again
 * using #LSR_desc_store().
 *
 * @param[in] id ID of the resource to be retrieved, without the namespace.
 *
 * @param[out] rsrc Resource handle to be populated with the found resource. It
 *  should be freed with #LSR_desc_free(). If NULL, the resource is only
 *  checked for existence (much faster). On a non-success return code, the
 *  handle may be garbage.
 *
 * @return LSUP_OK if the resource is found; LSUP_NORESULT if not found; <0
 *  on error.
 */
LSUP_rc
LSR_desc_get (const uuid_t id, LSR_Desc **rsrc);


/** @brief Free a DESC-R.
 */
void
LSR_desc_free (LSR_Desc *rsrc);


/** @brief Get resource metadata.
 *
 * Return all repository-managed triples about the resource.
 *
 * @param[in] rsrc Resource to be inspected.
 *
 * @return In-memory graph with metadata triples.
 */
LSUP_Graph *
LSR_desc_metadata (const LSR_Desc *rsrc);


/** @brief Get user-defined data.
 *
 * Return all user-defined triples in the resource in a single graph.
 *
 * The resulting graph IRI is the resource IRI with a random fragment string
 * appended.
 *
 * @param[in] rsrc Resource to be inspected.
 *
 * @return NULL-terminated array of in-memory graphs with data triples.
 */
LSUP_Graph **
LSR_desc_user_data (const LSR_Desc *rsrc);


/** @brief Store a DESC-R, overwriting any data if it already exists.
 *
 * This is a "create or overwrite" function that deletes any existing resource
 * under the given ID before storing the content of the in-memory resource
 * at hand.
 *
 * All data are copied and the resource may be freed after this operation.
 *
 * @param[in] rsrc Resource to be created or overwritten.
 */
LSUP_rc
LSR_desc_store (const LSR_Desc *rsrc);


/** @brief Perform a delta update on a stored resource.
 *
 * This function operates directly on a stored resource without the need to
 * provide an in-memory DESC-R. It first deletes triples by given patterns,
 * then adds triples. Both steps are optional.
 *
 * @param[in] id ID of the resource to be modified, without the namespace.
 *
 * @param[in] remove Array of 3-member array of terms. Each set of
 *  terms represents the s, p, o bound terms. Any and all can be NULL, as in
 *  #LSUP_graph_remove(). The array is terminated by a `{NULL}` array.
 *
 * @param[in] add Array of triples to be added, terminated by a NULL.
 */
LSUP_rc
LSUP_desc_update (LSR_id id, LSUP_Term **remove, LSUP_Triple *add);


/** @brief Delete a DESC-R.
 *
 * TODO Soft-deletes to be implemented with versioning.
 *
 * @param[in] id Resource ID.
 *
 * @return LSUP_OK if the resource was found and deleted; LSUP_NOACTION if no
 *  resource was found for the given ID.
 */
LSUP_rc
LSUP_desc_delete (LSR_id id);

#endif /* _LSR_DESC_H */
